home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 10 / FM Towns Free Software Collection 10.iso / ms_dos / tool / make / src / make.c < prev    next >
Text File  |  1995-02-28  |  25KB  |  1,201 lines

  1. /*****************************************************
  2.  
  3.     make.c
  4.  
  5.     1993.7.29    make by Ken
  6.  
  7. ******************************************************/
  8. #include    <stdio.h>
  9. #include    <stdlib.h>
  10. #include    <string.h>
  11. #include    <ctype.h>
  12. #ifndef    LSIC
  13. #include    <sys/types.h>
  14. #endif
  15. #include    <sys/stat.h>
  16. #include    "defs.h"
  17.  
  18. #define    SBDFALC    8
  19. #define    MKDFALC    16
  20.  
  21.     char    *version = "%s version 0.12 1995.01.26 Nanno-NET(Ken)\n";
  22.  
  23.     int    debug_flag = 0;
  24.     int    all_target_flag = FALSE;
  25.  
  26.     ENVPTR    *env_tab[HASH_SIZE];
  27.     TAGPTR    *tag_tab[HASH_SIZE];
  28.  
  29.     TAGPTR    *tag_top = NULL;
  30.     TAGPTR    *tag_now = NULL;
  31.  
  32.     TAGPTR    *tag_list = NULL;
  33.  
  34.     RULPTR    *rule_top = NULL;
  35.     SUBPTR    *rule_now = NULL;
  36.  
  37.     CMDPTR    *make_top = NULL;
  38.     CMDPTR    *make_btm = NULL;
  39.  
  40. static    SUBPTR    *sub_free = NULL;
  41. static    MAKPTR    *mk_free = NULL;
  42.  
  43. extern    int    optind;
  44. extern    char    *optarg;
  45.  
  46. static    char    tmp_buff[STRLEN + 2];
  47. static    char    *def_rule[] = {
  48. #ifdef    UNIX
  49. # include    "default.c"
  50. #else
  51.         "CC=cc",
  52.         "CFLAGS=-O",
  53.         ".SUFFIXES: . .lzh .zip .zoo .lzs .gz .z .Z",
  54.         ".SUFFIXES: .dvi .tex .ref",
  55.         ".SUFFIXES: .lst .map .lnk .sym .mak .def",
  56.         ".SUFFIXES: .exe .exp .exg .com .rex",
  57.         ".SUFFIXES: .lib .obj .dlg .asm",
  58.         ".SUFFIXES: .o .a .c .cc .p .f .r .y .l .s .h",
  59.         ".c.obj:",
  60.         " $(CC) $(CFLAGS) -c $<",
  61. #endif
  62.         NULL
  63.     };
  64.  
  65. char    *trim(char *str)
  66. {
  67.     char    *p;
  68.  
  69.     while ( isspace(*str) )
  70.     str++;
  71.     for ( p = str + strlen(str) ; p > str && isspace(*(p - 1)) ; )
  72.     p--;
  73.     *p = '\0';
  74.  
  75.     return str;
  76. }
  77. char    *basename(char *buf, char *str)
  78. {
  79.     char *p;
  80.     char *s;
  81.  
  82.     if ( (p = strrchr(str, '/')) == NULL &&
  83.      (p = strrchr(str, '\\')) == NULL &&
  84.      (p = strrchr(str, ':')) == NULL )
  85.     p = str;
  86.  
  87. #ifdef    MAKE_OLD
  88.     if ( p != str )
  89.     str = p + 1;
  90. #endif
  91.  
  92.     if ( (p = strrchr(p, '.')) == NULL ) {
  93.     for ( p = str ; *p != '\0' ; p++ )
  94.         ;
  95.     }
  96.  
  97.     s = buf;
  98.     while ( *str != '\0' && str < p )
  99.     *(s++) = *(str++);
  100.     *s = '\0';
  101.  
  102.     return buf;
  103. }
  104. int    hash_calc(char *p)
  105. {
  106.     int     hs = 0;
  107.  
  108.     while ( *p != '\0' )
  109.     hs = hs * 31 + *(p++);
  110.     return (hs & HASH_MASK);
  111. }
  112. char    *get_env(char *name)
  113. {
  114.     int     hs;
  115.     ENVPTR  *ep;
  116.  
  117.     hs = hash_calc(name);
  118.     for ( ep = env_tab[hs] ; ep != NULL ; ep = ep->ev_next ) {
  119.     if ( strcmp(name, ep->ev_name) == 0 )
  120.         return ep->ev_para;
  121.     }
  122.     return "";
  123. }
  124. char    *set_env(char *name, char *para)
  125. {
  126.     int     hs;
  127.     ENVPTR  *ep;
  128.  
  129.     hs = hash_calc(name);
  130.     for ( ep = env_tab[hs] ; ep != NULL ; ep = ep->ev_next ) {
  131.     if ( strcmp(name, ep->ev_name) == 0 ) {
  132.         FREE(ep->ev_para);
  133.         if ( (ep->ev_para = STRDUP(para)) == NULL ) {
  134.         fprintf(stderr, "strdup malloc error '%s'\n", para);
  135.         exit(2);
  136.         }
  137.         return ep->ev_para;
  138.     }
  139.     }
  140.  
  141.     if ( (ep = (ENVPTR *)MALLOC(sizeof(ENVPTR) + strlen(name))) == NULL ) {
  142.     fprintf(stderr, "envptr malloc error\n");
  143.     exit(2);
  144.     }
  145.  
  146.     if ( (ep->ev_para = STRDUP(para)) == NULL ) {
  147.     fprintf(stderr, "strdup malloc error '%s'\n", para);
  148.     exit(2);
  149.     }
  150.  
  151.     strcpy(ep->ev_name, name);
  152.     ep->ev_next = env_tab[hs];
  153.     env_tab[hs] = ep;
  154.  
  155.     return ep->ev_para;
  156. }
  157. char    *get_macro(char *str)
  158. {
  159.     int  n, len;
  160.     char *p, *s;
  161.     char tmp[80 + 2];
  162.     char rep[STRLEN + 2];
  163.     char dmy[STRLEN + 2];
  164.  
  165.     for ( n = 0 ; *str != '\0' && *str != ':' ; ) {
  166.     if ( n < 80 )
  167.         tmp[n++] = *(str++);
  168.     }
  169.     tmp[n] = '\0';
  170.  
  171.     if ( strchr(tmp, '*') != NULL || strchr(tmp, '?') != NULL ) {
  172.     n = 0;
  173.     while ( (p = wild_file(tmp)) != NULL ) {
  174.         if ( n < STRLEN )
  175.         dmy[n++] = ' ';
  176.         while ( n < STRLEN && *p != '\0' )
  177.         dmy[n++] = *(p++);
  178.     }
  179.     dmy[n] = '\0';
  180.     p = dmy + 1;
  181.     } else
  182.     p = get_env(tmp);
  183.  
  184.     if ( *str == ':' ) {
  185.     str++;
  186.     for ( n = 0 ; *str != '\0' && *str != '=' ; ) {
  187.         if ( n < 80 )
  188.             tmp[n++] = *(str++);
  189.         }
  190.         tmp[n] = '\0';
  191.     if ( *str == '=' )
  192.         str++;
  193.     len = strlen(tmp);
  194.     n = 0;
  195.     while ( n < STRLEN && *p != '\0' ) {
  196.         if ( strncmp(p, tmp, len) == 0 ) {
  197.         p += len;
  198.         for ( s = str ; n < STRLEN && *s != '\0' ; )
  199.             rep[n++] = *(s++);
  200.         } else
  201.         rep[n++] = *(p++);
  202.     }
  203.     rep[n] = '\0';
  204.     p = rep;
  205.     }
  206.  
  207.     return STRDUP(p);
  208. }
  209.  
  210. char    *macro(char *buf, char *str, int max)
  211. {
  212.     int     n = 0;
  213.     int     ch;
  214.     char    *t;
  215.     char    *b;
  216.     static int nest = 0;
  217.  
  218.     while ( *str != '\0' && n < max ) {
  219.     switch(*str) {
  220.     case '$':
  221.         str++;
  222.         switch(*(str++)) {
  223.         case '$':
  224.         buf[n++] = '$';
  225.         break;
  226.  
  227.         case '*':
  228.         t = get_env("*");        /* target base name */
  229.         goto STRCPY;
  230.         case '<':                /* depend name */
  231.         t = get_env("<");
  232.         goto STRCPY;
  233.         case '@':                /* target name */
  234.         t = get_env("@");
  235.         goto STRCPY;
  236.         case '?':                /* all depend name */
  237.         t = get_env("?");
  238.         STRCPY:
  239.         while ( *t != '\0' && n < max )
  240.             buf[n++] = *(t++);
  241.         break;
  242.  
  243.         case '(':
  244.         ch = ')';
  245.         goto MACRO;
  246.         case '{':
  247.         ch = '}';
  248.         MACRO:
  249.         if ( (b = strchr(str, ch)) != NULL ) {
  250.             *b = '\0';
  251.             if ( ++nest >= NEST_MAX ) {
  252.             fprintf(stderr, "deep nesting macro '%s'\n", str);
  253.             exit(2);
  254.             }
  255.             t = get_macro(str);
  256.             *(b++) = ch;
  257.             str = b;
  258.             macro(buf + n, t, max - n);
  259.             while ( buf[n] != '\0' )
  260.             n++;
  261.             FREE(t);
  262.             nest--;
  263.             break;
  264.         }
  265.  
  266.         default:
  267.         str -= 2;
  268.         buf[n++] = *(str++);
  269.         break;
  270.         }
  271.         break;
  272.     default:
  273.         buf[n++] = *(str++);
  274.         break;
  275.     }
  276.     }
  277.     buf[n] = '\0';
  278.  
  279.     return buf;
  280. }
  281. int    env_load(char *name)
  282. {
  283.     int n;
  284.     char *para;
  285.     char *p;
  286.     char buf[STRLEN + 2];
  287.  
  288.     if ( (para = strchr(name, '=')) == NULL )
  289.     return ERR;
  290.  
  291.     if ( para > name && *(para - 1) == '+' ) {
  292.     *(para - 1) = '\0';
  293.     para++;
  294.     name = trim(name);
  295.     p = get_env(name);
  296.     for ( n = 0 ; n < STRLEN && *p != '\0' ; )
  297.         buf[n++] = *(p++);
  298.     while ( n < STRLEN && *para != '\0' )
  299.         buf[n++] = *(para++);
  300.     buf[n] = '\0';
  301.     para = trim(buf);
  302.     set_env(name, para);
  303.  
  304.     } else {
  305.     *(para++) = '\0';
  306.     name = trim(name);
  307.     para = trim(para);
  308.     set_env(name, para);
  309.     }
  310.  
  311.     if ( debug_flag > 1 )
  312.     fprintf(stderr, "set %s = %s\n", name, para);
  313.  
  314.     return FALSE;
  315. }
  316. TAGPTR    *set_target(char *file)
  317. {
  318.     int    hs;
  319.     TAGPTR *tp;
  320.  
  321.     hs = hash_calc(file);
  322.     for ( tp = tag_tab[hs] ; tp != NULL ; tp = tp->tg_next ) {
  323.     if ( strcmp(file, tp->tg_file) == 0 )
  324.         return tp;
  325.     }
  326.  
  327.     if ( (tp = (TAGPTR *)MALLOC(sizeof(TAGPTR) + strlen(file))) == NULL ) {
  328.     fprintf(stderr, "tagptr malloc error '%s'\n", file);
  329.     exit(2);
  330.     }
  331.  
  332.     strcpy(tp->tg_file, file);
  333.     tp->tg_list = NULL;
  334.     tp->tg_link = NULL;
  335.     tp->tg_cmds = NULL;
  336.     tp->tg_status = TAG_NOCHECK;
  337.     tp->tg_time = NOTIME;
  338.     tp->tg_next = tag_tab[hs];
  339.     tag_tab[hs] = tp;
  340.  
  341.     return tp;
  342. }
  343. TAGPTR    *get_target(char *file)
  344. {
  345.     int    hs;
  346.     TAGPTR *tp;
  347.  
  348.     hs = hash_calc(file);
  349.     for ( tp = tag_tab[hs] ; tp != NULL ; tp = tp->tg_next ) {
  350.     if ( strcmp(file ,tp->tg_file) == 0 )
  351.         return tp;
  352.     }
  353.     return NULL;
  354. }
  355.  
  356. MAKPTR    *makptr_alloc(char *file)
  357. {
  358.     int n;
  359.     MAKPTR  *mp;
  360.     TAGPTR  *tp;
  361.  
  362.     if ( mk_free == NULL ) {
  363.     if ( (mp = (MAKPTR *)MALLOC(sizeof(MAKPTR) * MKDFALC )) == NULL ) {
  364.         fprintf(stderr, "makptr malloc error '%s'\n", file);
  365.         exit(2);
  366.     }
  367.     for ( n = 0 ; n < MKDFALC ; n++ ) {
  368.         mp->mk_next = mk_free;
  369.         mk_free = mp;
  370.         mp++;
  371.     }
  372.     }
  373.  
  374.     mp = mk_free;
  375.     mk_free = mp->mk_next;
  376.  
  377.     tp = set_target(file);
  378.     mp->mk_file = tp->tg_file;
  379.     mp->mk_next = NULL;
  380.     return mp;
  381. }
  382. void    makptr_free(MAKPTR *mp)
  383. {
  384.     mp->mk_next = mk_free;
  385.     mk_free = mp;
  386. }
  387. MAKPTR    *makptr_wild(char *file)
  388. {
  389.     MAKPTR  *mp;
  390.     MAKPTR  top;
  391.     char    *p;
  392.  
  393.     if ( strchr(file, '*') != NULL || strchr(file, '?') != NULL ) {
  394.     top.mk_next = NULL;
  395.     mp = ⊤
  396.     while ( (p = wild_file(file)) != NULL ) {
  397.         mp->mk_next = makptr_alloc(p);
  398.         mp = mp->mk_next;
  399.     }
  400.     return top.mk_next;
  401.  
  402.     } else
  403.     return makptr_alloc(file);
  404. }
  405. MAKPTR    *depend_link(char **ptr)
  406. {
  407.     char    *p;
  408.     char    *s;
  409.     MAKPTR  *mp = NULL;
  410.  
  411.     p = *ptr;
  412. LOOP:
  413.     while ( isspace(*p) )
  414.     p++;
  415.  
  416.     if ( *p != '\0' ) {
  417.     for ( s = p ; *s != '\0' ; s++ ) {
  418.         if ( isspace(*s) )
  419.         break;
  420.     }
  421.     if ( *s == '\0' )
  422.         mp = makptr_wild(p);
  423.     else {
  424.         *s = '\0';
  425.         mp = makptr_wild(p);
  426.         *(s++) = ' ';
  427.     }
  428.     p = s;
  429.     if ( mp == NULL )
  430.         goto LOOP;
  431.     }
  432.  
  433.     *ptr = p;
  434.     return mp;
  435. }
  436. void    target_alloc(char *file, char *para)
  437. {
  438.     MAKPTR  *mp, *bp, *ap;
  439.     TAGPTR  *tp;
  440.     char    tmp[STRLEN + 2];
  441.  
  442.     rule_now = NULL;
  443.     tp = get_target(file);
  444.     tag_now = set_target(file);
  445.     if ( tp == NULL ) {
  446.     tag_now->tg_list = tag_list;
  447.     tag_list = tag_now;
  448.     }
  449.     set_env("@", tag_now->tg_file);
  450.     set_env("*", basename(tmp, tag_now->tg_file));
  451.     set_env("<", "");
  452.     set_env("?", "");
  453.     para = macro(tmp, para, STRLEN);
  454.  
  455.     if ( tag_top == NULL )
  456.     tag_top = tag_now;
  457.  
  458.     while ( (mp = depend_link(¶)) != NULL ) {
  459.     do {
  460.         ap = bp = tag_now->tg_link;
  461.         while ( bp != NULL ) {
  462.         if ( strcmp(bp->mk_file, mp->mk_file) == 0 ) {
  463.             if ( ap == bp )
  464.             tag_now->tg_link = bp->mk_next;
  465.             else
  466.             ap->mk_next = bp->mk_next;
  467.             makptr_free(bp);
  468.             break;
  469.         }
  470.         ap = bp;
  471.         bp = bp->mk_next;
  472.         }
  473.  
  474.         if ( debug_flag > 1 )
  475.         fprintf(stderr, "target %s : %s\n", file, mp->mk_file);
  476.         bp = mp->mk_next;
  477.         mp->mk_next = tag_now->tg_link;
  478.         tag_now->tg_link = mp;
  479.         mp = bp;
  480.     } while ( mp != NULL );
  481.     }
  482.  
  483.     if ( tag_now->tg_link == NULL ) {
  484.     if ( debug_flag > 1 )
  485.         fprintf(stderr, "target %s :\n", file);
  486.     tag_now->tg_status = TAG_DEFEXEC;
  487.     }
  488. }
  489. void    target_link(char *file, char *para)
  490. {
  491.     int n;
  492.     char *p, *s;
  493.     char tmp[STRLEN + 2];
  494.  
  495.     while ( *file != '\0' ) {
  496.     for ( p = file ; *p != '\0' ; p++ ) {
  497.         if ( isspace(*p) ) {
  498.         *(p++) = '\0';
  499.         break;
  500.         }
  501.     }
  502.  
  503.     if ( strchr(file, '*') != NULL || strchr(file, '?') != NULL ) {
  504.         n = 0;
  505.         while ( (s = wild_file(file)) != NULL ) {
  506.         if ( n < STRLEN )
  507.             tmp[n++] = ' ';
  508.         while ( n < STRLEN && *s != '\0' )
  509.             tmp[n++] = *(s++);
  510.         }
  511.         tmp[n] = '\0';
  512.         target_link(tmp + 1, para);
  513.     } else
  514.         target_alloc(file, para);
  515.  
  516.     file = p;
  517.     while ( isspace(*file) )
  518.         file++;
  519.     }
  520. }
  521.  
  522. void    suff_init(char *str)
  523. {
  524.     char *p;
  525.     RULPTR *rp;
  526.  
  527.     while ( *str != '\0' ) {
  528.     while ( isspace(*str) )
  529.         str++;
  530.     p = str;
  531.     while ( !isspace(*str) && *str != '\0' )
  532.         str++;
  533.     if ( isspace(*str) )
  534.         *(str++) = '\0';
  535.  
  536.     if ( *p == '\0' )
  537.         continue;
  538.     else if ( strcmp(p, ".") == 0 )
  539.         p++;
  540.  
  541.         for ( rp = rule_top ; rp != NULL ; rp = rp->rl_next ) {
  542.         if ( strcmp(p, rp->rl_tag) == 0 )
  543.             break;
  544.         }
  545.  
  546.         if ( rp == NULL ) {
  547.             if ( (rp = (RULPTR *)MALLOC(sizeof(RULPTR) +
  548.                     strlen(p))) == NULL ) {
  549.             fprintf(stderr, "rulptr malloc error '%s'\n", p);
  550.             exit(2);
  551.             }
  552.         strcpy(rp->rl_tag, p);
  553.         rp->rl_flag = FALSE;
  554.         rp->rl_link = NULL;
  555.         rp->rl_next = rule_top;
  556.         rule_top = rp;
  557.  
  558.         if ( debug_flag > 1 )
  559.         fprintf(stderr, "suffix %%%s\n", rp->rl_tag);
  560.         }
  561.     }
  562. }
  563. SUBPTR    *subptr_alloc(char *name)
  564. {
  565.     int n;
  566.     SUBPTR *sp;
  567.  
  568.     if ( sub_free == NULL ) {
  569.         if ( (sp = (SUBPTR *)MALLOC(sizeof(SUBPTR) * SBDFALC)) == NULL )
  570.         return NULL;
  571.     for ( n = 0 ; n < SBDFALC ; n++ ) {
  572.         sp->sb_next = sub_free;
  573.         sub_free = sp;
  574.         sp++;
  575.     }
  576.     }
  577.  
  578.     sp = sub_free;
  579.     sub_free = sp->sb_next;
  580.     return sp;
  581. }
  582. int    suff_check(char *str)        /* .c.o */
  583. {
  584.     int n;
  585.     RULPTR *tp;        /* .o */
  586.     RULPTR *dp;        /* .c */
  587.     SUBPTR *sp;
  588.     SUBPTR *ap;
  589.  
  590.     for ( dp = rule_top ; dp != NULL ; dp = dp->rl_next ) {
  591.     n = strlen(dp->rl_tag);
  592.     if ( n > 0 && strncmp(str, dp->rl_tag, n) == 0 ) {
  593.         for ( tp = rule_top ; tp != NULL ; tp = tp->rl_next ) {
  594.         if ( strcmp(str + n, tp->rl_tag) == 0 )
  595.             goto RULESET;
  596.         }
  597.     }
  598.     }
  599.     return FALSE;
  600.  
  601. RULESET:
  602.  
  603.     for ( ap = sp = tp->rl_link ; sp != NULL ; ) {
  604.     if ( strcmp(dp->rl_tag, sp->sb_dep) == 0 ) {
  605.         if ( ap != sp ) {
  606.         ap->sb_next = sp->sb_next;
  607.         sp->sb_next = tp->rl_link;
  608.         tp->rl_link = sp;
  609.         }
  610.         sp->sb_cmds = NULL;
  611.         break;
  612.     }
  613.     ap = sp;
  614.     sp = sp->sb_next;
  615.     }
  616.  
  617.     if ( sp == NULL ) {
  618.         if ( (sp = subptr_alloc(dp->rl_tag)) == NULL ) {
  619.         fprintf(stderr, "subptr malloc error '%s'\n", dp->rl_tag);
  620.         exit(2);
  621.         }
  622.         sp->sb_dep = dp->rl_tag;
  623.         sp->sb_cmds = NULL;
  624.         sp->sb_next = tp->rl_link;
  625.         tp->rl_link = sp;
  626.     }
  627.  
  628.     tag_now = NULL;
  629.     rule_now = sp;
  630.  
  631.     if ( debug_flag > 1 )
  632.     fprintf(stderr, "rule %%%s : %%%s\n", tp->rl_tag, dp->rl_tag);
  633.  
  634.     return TRUE;
  635. }
  636. int    make_load(char *file)
  637. {
  638.     char    *para;
  639.  
  640.     set_env("*", "");
  641.     set_env("@", "");
  642.     set_env("<", "");
  643.     set_env("?", "");
  644.     file = macro(tmp_buff, file, STRLEN);
  645.  
  646.     if ( (para = strchr(file, ':')) == NULL )
  647.     return ERR;
  648.     else if ( strcmp(file, ".SUFFIXES") == 0 )
  649.     para = file + 9;
  650.  
  651.     *(para++) = '\0';
  652.     file = trim(file);
  653.     para = trim(para);
  654.  
  655.     if ( *para == ':' )
  656.     para = trim(++para);
  657.  
  658.     if ( suff_check(file) )
  659.     return FALSE;
  660.     else if ( strcmp(file, ".SUFFIXES") == 0 )
  661.     suff_init(para);
  662.     else
  663.         target_link(file, para);
  664.  
  665.     return FALSE;
  666. }
  667. int    cmds_load(CMDPTR *cp)
  668. {
  669.     char *p;
  670.  
  671.     if ( tag_now != NULL ) {
  672.     cp->cd_next = tag_now->tg_cmds;
  673.     tag_now->tg_cmds = cp;
  674.  
  675.     } else if ( rule_now != NULL ) {
  676.     cp->cd_next = rule_now->sb_cmds;
  677.     rule_now->sb_cmds = cp;
  678.  
  679.     } else
  680.     return ERR;
  681.  
  682.     p = cp->cd_exec;
  683.     while ( isspace(*p) )
  684.     p++;
  685.  
  686.     if ( p > cp->cd_exec )
  687.     strcpy(cp->cd_exec, p);
  688.  
  689.     if ( debug_flag > 1 )
  690.     fprintf(stderr, "cmds : %s\n", cp->cd_exec);
  691.  
  692.     return FALSE;
  693. }
  694. int    make_parse()
  695. {
  696.     int st;
  697.     CMDPTR *cp, *tp;
  698.  
  699.     suff_init(get_env("SUFFIXES"));
  700.  
  701.     for ( cp = tp = make_top ; cp != NULL ; cp = tp ) {
  702.     tp = cp->cd_next;
  703.     if ( isspace(cp->cd_exec[0]) )
  704.         st = cmds_load(cp);
  705.     else {
  706.         st = make_load(cp->cd_exec);
  707.         FREE(cp);
  708.     }
  709.  
  710.     if ( st ) {
  711.         fprintf(stderr, "make parse error '%s'\n", cp->cd_exec);
  712.         exit(2);
  713.     }
  714.     }
  715.  
  716.     tag_now = NULL;
  717.     rule_now = NULL;
  718.  
  719.     return FALSE;
  720. }
  721. int    make_save(char *str)
  722. {
  723.     CMDPTR *cp;
  724.  
  725.     if ( (cp = (CMDPTR *)MALLOC(sizeof(CMDPTR) + strlen(str))) == NULL ) {
  726.     fprintf(stderr, "make load malloc error '%s'\n", str);
  727.     exit(2);
  728.     }
  729.  
  730.     strcpy(cp->cd_exec, str);
  731.     cp->cd_next = NULL;
  732.  
  733.     if ( make_top == NULL )
  734.     make_top = cp;
  735.     else
  736.     make_btm->cd_next = cp;
  737.     make_btm = cp;
  738.  
  739.     return FALSE;
  740. }
  741. int    parse_load(char *para)
  742. {
  743.     char    *str;
  744.  
  745.     str = para;
  746.  
  747.     while ( isspace(*str) )
  748.     str++;
  749.  
  750.     if ( *str == '\0' || *str == '\n' || *str == '#' )
  751.     return FALSE;
  752.  
  753.     while ( isalnum(*str) || *str == '_' || *str == '.' )
  754.     str++;
  755.  
  756.     while ( isspace(*str) )
  757.     str++;
  758.  
  759.     if ( *str == '=' )
  760.     return env_load(para);
  761.     else
  762.     return make_save(para);
  763. }
  764. int    file_load(char *file)
  765. {
  766.     int     len = 0;
  767.     int     line = 0;
  768.     FILE    *fp;
  769.     char    *p;
  770.  
  771.     if ( (fp = fopen(file, "r")) == NULL )
  772.     return ERR;
  773.  
  774.     if ( debug_flag > 0 )
  775.     fprintf(stderr, "rule file load '%s'\n", file);
  776.  
  777.     while ( fgets(tmp_buff + len, STRLEN - len, fp) != NULL ) {
  778.     line++;
  779.  
  780.     if ( (p = strchr(tmp_buff, '\n')) != NULL )
  781.         *p = '\0';
  782.     if ( (p = strchr(tmp_buff, '#')) != NULL )
  783.         *p = '\0';
  784.  
  785.     p = tmp_buff + strlen(tmp_buff) - 1;
  786.     if ( p >= tmp_buff && *p == '\\' ) {
  787.         len = p - tmp_buff;
  788.         continue;
  789.     }
  790.  
  791.     len = 0;
  792.     if ( parse_load(tmp_buff) ) {
  793.         fprintf(stderr, "parse error '%s' in %d line\n", file, line);
  794.         fprintf(stderr, "%s\n", tmp_buff);
  795.         exit(2);
  796.     }
  797.     }
  798.  
  799.     fclose(fp);
  800.     return FALSE;
  801. }
  802.  
  803. /**************************************************************/
  804.  
  805. int    suff_cmp(char *file, char *ptn)
  806. {
  807.     int n;
  808.     char *p;
  809.  
  810.     if ( *ptn == '\0' ) {
  811.     if ( (p = strrchr(file, '/')) == NULL &&
  812.          (p = strrchr(file, '\\')) == NULL )
  813.         p = file;
  814.  
  815.     if ( strchr(p, '.') == NULL )
  816.         return strlen(file);
  817.     else
  818.         return (-1);
  819.  
  820.     } else if ( (n = strlen(file) - strlen(ptn)) > 0 &&
  821.         strcmp(file + n, ptn) == 0 )
  822.     return n;
  823.     else
  824.     return (-1);
  825. }
  826. int    rule_exec(TAGPTR *tag, char *file)
  827. {
  828.     int    n, i;
  829.     RULPTR *rp;
  830.     SUBPTR *sp;
  831.     TAGPTR *tp;
  832.     MAKPTR *mp;
  833.     struct stat st;
  834.     time_t ti = NOTIME;
  835.     char   tmp[STRLEN + 2];
  836.     static int deps = 0;
  837.  
  838.     deps++;
  839.  
  840.     if ( tag != NULL )
  841.     file = tag->tg_file;
  842.  
  843.     for ( rp = rule_top ; rp != NULL ; rp = rp->rl_next ) {
  844.     if ( rp->rl_flag == FALSE &&
  845.         (n = suff_cmp(file, rp->rl_tag)) > 0 ) {
  846.  
  847.         rp->rl_flag = TRUE;
  848.         strcpy(tmp, file);
  849.  
  850.         if ( tag != NULL ) {
  851.             for ( sp = rp->rl_link ; sp != NULL ; sp = sp->sb_next ) {
  852.                 strcpy(tmp + n, sp->sb_dep);
  853.             for ( mp = tag->tg_link ; mp != NULL ; mp = mp->mk_next ) {
  854.                 if ( strcmp(tmp, mp->mk_file) == 0 )
  855.                 goto RULEMACH;
  856.             }
  857.         }
  858.         }
  859.  
  860.         for ( sp = rp->rl_link ; sp != NULL ; sp = sp->sb_next ) {
  861.             strcpy(tmp + n, sp->sb_dep);
  862.  
  863.         if ( debug_flag > 1 ) {
  864.             for ( i = 0 ; i < deps ; i++ )
  865.             fprintf(stderr, " ");
  866.            fprintf(stderr, "chk rule %s ? %s\n", file, tmp);
  867.         }
  868.  
  869.         if ( !stat(tmp, &st) ) {
  870.             ti = st.st_mtime;
  871.             goto RULEMACH;
  872.         } else if ( (tp = get_target(tmp)) != NULL &&
  873.                 rule_exec(tp, NULL) )
  874.             goto RULEMACH;
  875.         else if ( rule_exec(NULL, tmp) )
  876.             goto RULEMACH;
  877.         }
  878.         rp->rl_flag = FALSE;
  879.         break;
  880.     }
  881.     }
  882.  
  883.     deps--;
  884.     return FALSE;
  885.  
  886. RULEMACH:
  887.     if ( debug_flag > 1 ) {
  888.     for ( n = 0 ; n < deps ; n++ )
  889.         fprintf(stderr, " ");
  890.         fprintf(stderr, "def rule %s -> %s\n", file, tmp);
  891.     }
  892.  
  893.     target_alloc(file, tmp);
  894.     tp = get_target(tmp);
  895.     tp->tg_time = ti;
  896.     if ( tag_now->tg_cmds == NULL )
  897.     tag_now->tg_cmds = sp->sb_cmds;
  898.     rp->rl_flag = FALSE;
  899.  
  900.     deps--;
  901.     return TRUE;
  902. }
  903. void    cmds_exec(CMDPTR *cp)
  904. {
  905.     int     n;
  906.     char    *p;
  907.     int     noecho = FALSE;
  908.     int     noerrret = FALSE;
  909.     int     useshell = FALSE;
  910.  
  911.     if ( cp == NULL )
  912.     return;
  913.  
  914.     cmds_exec(cp->cd_next);
  915.     p = macro(tmp_buff, cp->cd_exec, STRLEN);
  916.  
  917.     if ( debug_flag > 1 )
  918.     fprintf(stderr, "exec %s\n", p);
  919.  
  920.     for ( ; ; ) {
  921.         if ( *p == '@' ) {
  922.         p++;
  923.         noecho = TRUE;
  924.         } else if ( *p == '-' ) {
  925.         p++;
  926.         noerrret = TRUE;
  927.         } else if ( *p == '+' ) {
  928.         p++;
  929.         useshell = TRUE;
  930.         } else
  931.         break;
  932.     }
  933.  
  934.     if ( !noecho )
  935.     fprintf(stderr, "%s\n", p);
  936.  
  937.     if ( debug_flag <= 1 && (n = SYSTEM(useshell, p)) && !noerrret ) {
  938.     fprintf(stderr, "*** error code %d %s\n", n, p);
  939.     exit(1);
  940.     }
  941. }
  942. int    make_exec(TAGPTR *tp)
  943. {
  944.     int rt = FALSE;
  945.     int n;
  946.     MAKPTR *mp;
  947.     TAGPTR *dp;
  948.     char *p;
  949.     struct stat st;
  950.     static int deps = 0;
  951.  
  952.     if ( tp == NULL || (tp->tg_status & TAG_UPDATE) )
  953.     return FALSE;
  954.  
  955.     deps++;
  956.     tp->tg_status |= TAG_UPDATE;
  957.  
  958.     if ( (tp->tg_status & TAG_DEFEXEC) )
  959.     rt = TRUE;
  960.  
  961.     if ( tp->tg_cmds == NULL )
  962.     rule_exec(tp, NULL);
  963.  
  964.     for ( mp = tp->tg_link ; mp != NULL ; mp = mp->mk_next ) {
  965.     dp = get_target(mp->mk_file);
  966.     make_exec(dp);
  967.  
  968.     if ( tp->tg_time == NOTIME ) {
  969.         if ( stat(tp->tg_file, &st) )
  970.         tp->tg_time = NOFILE;
  971.         else
  972.         tp->tg_time = st.st_mtime;
  973.     }
  974.  
  975.     if ( dp->tg_time == NOTIME ) {
  976.         if ( stat(dp->tg_file, &st) ) {
  977.         fprintf(stderr, "not found depend file '%s'\n", dp->tg_file);
  978.         exit(1);
  979.         }
  980.         dp->tg_time = st.st_mtime;
  981.     }
  982.  
  983.     if ( debug_flag > 0 ) {
  984.         for ( n = 0 ; n < deps ; n++ )
  985.         fprintf(stderr, " ");
  986.         fprintf(stderr, "check %s(%ld) ? %s(%ld) %s\n",
  987.         tp->tg_file, tp->tg_time,
  988.         dp->tg_file, dp->tg_time,
  989.         tp->tg_time < dp->tg_time ? "domake" : "");
  990.     }
  991.  
  992.     if ( tp->tg_time < dp->tg_time )
  993.         rt = TRUE;
  994.     }
  995.  
  996.     if ( rt ) {
  997.     set_env("*", basename(tmp_buff, tp->tg_file));
  998.     set_env("@", tp->tg_file);
  999.     if ( (mp = tp->tg_link) != NULL ) {
  1000.         set_env("<", mp->mk_file);
  1001.         n = 0;
  1002.         for ( ; ; ) {
  1003.         p = mp->mk_file;
  1004.         while ( *p != '\0' && n < STRLEN )
  1005.             tmp_buff[n++] = *(p++);
  1006.         if ( (mp = mp->mk_next) == NULL )
  1007.             break;
  1008.         tmp_buff[n++] = ' ';
  1009.         }
  1010.         tmp_buff[n] = '\0';
  1011.         set_env("?", tmp_buff);
  1012.     } else {
  1013.         set_env("<", "");
  1014.         set_env("?", "");
  1015.     }
  1016.  
  1017.         cmds_exec(tp->tg_cmds);
  1018.     time(&(tp->tg_time));
  1019.     }
  1020.  
  1021.     deps--;
  1022.     return rt;
  1023. }
  1024. void    make_list(TAGPTR *tp)
  1025. {
  1026.     if ( tp != NULL ) {
  1027.     make_list(tp->tg_list);
  1028.     make_exec(tp);
  1029.     }
  1030. }
  1031.  
  1032. void    free_memory()
  1033. {
  1034.     int n;
  1035.     int a;
  1036.     long l = 0L;
  1037.     char *tmp[32];
  1038.  
  1039.     a = (16 * 1024);
  1040.     n = 0;
  1041.     for ( ; n < 32 && a > 4 ; ) {
  1042.     if ( (tmp[n] = (char *)MALLOC(a)) == NULL )
  1043.         a /= 2;
  1044.     else {
  1045.         l += a;
  1046.         n++;
  1047.     }
  1048.     }
  1049.     for ( a = 0 ; a < n ; a++ )
  1050.     FREE(tmp[a]);
  1051.  
  1052.     fprintf(stderr, "free memory size %ld\n", l);
  1053. }
  1054.  
  1055. void    usage(char *prog)
  1056. {
  1057. #ifdef    MAKE_OLD
  1058.     fprintf(stderr, "Usage: %s [-dv] [-t <Target>] [Makefile...]\n", prog);
  1059. #else
  1060.     fprintf(stderr, "Usage: %s [-a] [-dv] [-f <Makefile>] [Target...]\n", prog);
  1061. #endif
  1062. }
  1063. int    main(int ac, char *av[], char *ev[])
  1064. {
  1065.     int     n;
  1066.     int     mx = 1;
  1067.     int     mkc = 0;
  1068.     char    *mkv[10];
  1069.     int     tgc = 0;
  1070.     char    *tgv[10];
  1071.     char    *p;
  1072.     TAGPTR  *tp;
  1073.  
  1074.     for ( ; ; ) {
  1075.     while ( (n = getopt(ac, av, "advf:t:D:V")) != EOF ) {
  1076.         switch(n) {
  1077.         case 'a':
  1078.         all_target_flag = TRUE;
  1079.         break;
  1080.         case 'd':
  1081.         debug_flag += 2;
  1082.         break;
  1083.         case 'v':
  1084.         debug_flag += 1;
  1085.         break;
  1086.         case 'f':
  1087.         if ( mkc >= 10 ) {
  1088.             fprintf(stderr, "makefile overflow '%s'\n", optarg);
  1089.             exit(2);
  1090.         }
  1091.         mkv[mkc++] = optarg;
  1092.         break;
  1093.         case 't':
  1094.         if ( tgc >= 10 ) {
  1095.             fprintf(stderr, "target overflow '%s'\n", optarg);
  1096.             exit(2);
  1097.         }
  1098.         tgv[tgc++] = optarg;
  1099.         break;
  1100.         case 'D':
  1101.         if ( env_load(strcpy(tmp_buff, optarg)) )
  1102.             set_env(optarg, "");
  1103.         break;
  1104.         case 'V':
  1105.         fprintf(stderr, version, av[0]);
  1106.         return 0;
  1107.         default:
  1108.         usage(av[0]);
  1109.         exit(2);
  1110.         }
  1111.     }
  1112.     if ( optind >= ac )
  1113.         break;
  1114.     av[mx++] = av[optind++];
  1115.     }
  1116.  
  1117.     for ( n = 0 ; def_rule[n] != NULL ; n++ )
  1118.     parse_load(strcpy(tmp_buff, def_rule[n]));
  1119.  
  1120.     set_env("MAKE", av[0]);
  1121.     tmp_buff[0] = '\0';
  1122.     if ( all_target_flag )
  1123.     strcpy(tmp_buff, "-a");
  1124.     if ( debug_flag >= 2 )
  1125.     strcat(tmp_buff, " -d");
  1126.     if ( debug_flag >= 1 )
  1127.     strcat(tmp_buff, " -v");
  1128.     set_env("MAKEFLAGS", tmp_buff);
  1129.  
  1130.     if ( (p = get_env("MAKEFILE")) != NULL && *p != '\0' )
  1131.     file_load(p);
  1132.  
  1133.     for ( n = 0 ; ev[n] != NULL ; n++ )
  1134.     env_load(strcpy(tmp_buff, ev[n]));
  1135.  
  1136. #ifdef    MAKE_OLD
  1137.     for ( n = 1 ; n < mx ; n++ ) {
  1138.     if ( strchr(av[n], '=') == NULL ) {
  1139.         if ( mkc >= 10 ) {
  1140.         fprintf(stderr, "makefile overflow '%s'\n", av[n]);
  1141.         exit(2);
  1142.         }
  1143.         mkv[mkc++] = av[n];
  1144.     }
  1145.     }
  1146. #endif
  1147.  
  1148.     if ( mkc > 0 ) {
  1149.     for ( n = 0 ; n < mkc ; n++ ) {
  1150.         if ( file_load(mkv[n]) ) {
  1151.         fprintf(stderr, "can't open '%s'\n", mkv[n]);
  1152.         exit(1);
  1153.         }
  1154.     }
  1155.     } else {
  1156.     if ( file_load("Makefile") && file_load("makefile") ) {
  1157.         fprintf(stderr, "can't open makefile\n");
  1158.         exit(1);
  1159.     }
  1160.     }
  1161.  
  1162.     for ( n = 1 ; n < mx ; n++ ) {
  1163.     if ( env_load(strcpy(tmp_buff, av[n])) ) {
  1164. #ifndef    MAKE_OLD
  1165.         if ( tgc >= 10 ) {
  1166.         fprintf(stderr, "target overflow '%s'\n", av[n]);
  1167.         exit(2);
  1168.         }
  1169.         tgv[tgc++] = av[n];
  1170. #endif
  1171.     }
  1172.     }
  1173.  
  1174.     make_parse();
  1175.  
  1176.     if ( tgc > 0 ) {
  1177.         for ( n = 0 ; n < tgc ; n++ ) {
  1178.         if ( (tp = get_target(tgv[n])) == NULL ) {
  1179.             fprintf(stderr, "No rule to make target `%s'.\n", tgv[n]);
  1180.         exit(2);
  1181.         } else if ( !make_exec(tp) )
  1182.             fprintf(stderr, "`%s' is up to date.\n", tp->tg_file);
  1183.     }
  1184.     } else if ( all_target_flag ) {
  1185.     make_list(tag_list);
  1186.  
  1187.     } else {
  1188. #ifdef    MAKE_OLD
  1189.     make_list(tag_list);
  1190. #else
  1191.     if ( !make_exec(tag_top) )
  1192.         fprintf(stderr, "`%s' is up to date.\n", tag_top->tg_file);
  1193. #endif
  1194.     }
  1195.  
  1196.     if ( debug_flag > 1 )
  1197.     free_memory();
  1198.  
  1199.     return 0;
  1200. }
  1201.